package com.hsck.order.kds.base.utils

import kotlin.reflect.KProperty1
import kotlin.reflect.full.memberProperties

/**
 * @author isnoam
 * @package_name DataProcessor
 * @date 2024-09-12
 * DataProcessor 是一个通用工具类，可以处理任意类型的数据对象，
 * 通过反射提取对象的属性值，并根据指定字段返回对应的数据。
 *
 * @param T 泛型类型，表示处理的数据类型，要求为任意类型（Any）。
 */
class DataProcessor<T : Any> {

    /**
     * 将给定对象转换为字段名-字段值的映射关系。
     *
     * 这个方法通过 Kotlin 的反射机制来动态获取对象的所有属性及其对应的值。
     *
     * @receiver T 类型的对象，它是当前处理的数据对象。
     * @return 返回一个 Map，其中键为属性名称，值为对应的属性值。
     */
    private fun T.toFieldMap(): Map<String, Any?> {
        // 使用反射获取对象的所有属性，并将它们转换为字段名与字段值的映射
        return this::class.memberProperties
            .filterIsInstance<KProperty1<T, Any?>>() // 确保是 KProperty1 类型的属性（即可以获取值的属性）
            .associate { prop -> prop.name to prop.get(this) } // 使用 associate 方法将属性名映射到属性值
    }

    /**
     * 处理数据列表，提取指定字段名的数据并返回字段值的列表。
     *
     * 根据输入的字段名字符串，分割出字段列表，然后从数据对象的字段映射中
     * 按顺序提取每个对象中对应字段的值，最终返回一个包含多个字段值列表的集合。
     *
     * @param arrayFields 字符串，表示以逗号分隔的字段名称列表。
     * @param arrayData List<T>，表示要处理的数据对象列表，每个对象是泛型类型 T。
     * @return 返回一个二维列表，外层列表包含多个对象，每个对象对应的字段值按顺序存储在内层列表中。
     */
    fun processListData(arrayFields: String, arrayData: List<T>): List<List<Any?>> {
        // 通过逗号分隔字段名，并去除空格，得到字段名的集合
        val fields = arrayFields.split(",").map { it.trim() }

        // 存储符合条件的字段值的最终结果列表
        val result = mutableListOf<List<Any?>>()

        // 遍历数据列表中的每一个数据对象
        for (dataObject in arrayData) {
            // 将当前对象转换为字段名-字段值的映射
            val fieldMap = dataObject.toFieldMap()
            // 用于存储该对象的字段值
            val resultList = mutableListOf<Any?>()

            // 遍历字段名集合，按顺序从字段映射中提取对应的字段值
            for (field in fields) {
                resultList.add(fieldMap[field])
            }

            // 如果 resultList 中有任何非空字段值，才将其添加到结果中
            if (resultList.any { it != null }) {
                result.add(resultList)
            }
        }
        // 返回最终结果列表，每个内层列表对应一个对象的字段值
        return result
    }
}
